//
//  CNetRequestManager.m
//  NetworkDemo
//
//  Created by InitialC on 2017/5/27.
//  Copyright © 2016年 InitialC. All rights reserved.
//

#import "CNetRequestManager.h"
#import "AFHTTPSessionManager.h"

#ifdef DEBUG
#define NetCLog(...) NSLog(__VA_ARGS__)
#else
#define NetCLog(...)
#endif
static NSMutableDictionary *dataTaskManager;

static NSString *authorizationToken = nil;
static NSString *httpHeaderField = nil;

@implementation CNetRequestManager

+ (NSInteger)networkReachabilityStatus {
    
    return [[AFNetworkReachabilityManager sharedManager] networkReachabilityStatus];
}

+ (BOOL)isReachable {
   return  [[AFNetworkReachabilityManager sharedManager] isReachable];
}

+ (void)setReachabilityStatusChangeBlock:(void (^)(NSInteger))block {
    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
        block(status);
    }];
}
+ (void)setToken:(NSString *)token withHttpHeader:(NSString *)header {
    authorizationToken = nil;
    httpHeaderField = nil;
    if (token == nil || header == nil) {
        return;
    }
    
    authorizationToken = [token copy];
    httpHeaderField = [header copy];
}

+ (void)load {
    [[AFNetworkReachabilityManager sharedManager] startMonitoring];
}

+ (NSMutableDictionary *)dataTaskManager {
    if (!dataTaskManager) {
        dataTaskManager = [[NSMutableDictionary alloc] init];
       
    }
    return dataTaskManager;
}

+ (AFHTTPSessionManager *)manager {
    static AFHTTPSessionManager *manager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        manager = [[AFHTTPSessionManager alloc] init];
        [manager.requestSerializer willChangeValueForKey: @"timeoutInterval"];
        manager.requestSerializer.timeoutInterval = kTimeOutInterval;
        [manager.requestSerializer didChangeValueForKey: @"timeoutInterval"];
        // 声明上传的是json格式的参数，需要你和后台约定好，不然会出现后台无法获取到你上传的参数问题
        //    manager.requestSerializer = [AFJSONRequestSerializer serializer]; // 上传JSON格式
        // 声明获取到的数据格式
        //    manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // AFN不会解析,数据是data，需要自己解析
        manager.responseSerializer = [AFJSONResponseSerializer serializer]; // AFN会JSON解析返回的数据
        manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: @"application/json", @"text/json", @"text/javascript",@"text/html", nil];
        manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 上传普通格式


    });
    if (authorizationToken !=  nil && httpHeaderField != nil) {
        [manager.requestSerializer setValue: authorizationToken  forHTTPHeaderField: httpHeaderField];
    }
    // 超时时间
    
    
    return manager;
}

+ (void)CGET:(NSString *)urlString
  parameters:(id)parameters
    progress:(void (^)(NSProgress * _Nonnull))downloadProgress
     success:(AFNSuccessBlock)success
     failure:(AFNErrorBlock)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    
    
    NSURLSessionDataTask *dataTask = [manager GET:urlString parameters: parameters progress: downloadProgress success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        success(responseObject,YES);
        [[self dataTaskManager] removeObjectForKey: urlString];
        
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        failure(error);
        
        [[self dataTaskManager] removeObjectForKey: urlString];
        
    }];
    
    [[self dataTaskManager] setValue: dataTask forKey: urlString];
}

+ (void)CGET:(NSString *)urlString
  parameters:(id)parameters
     success:(AFNSuccessBlock)success
     failure:(AFNErrorBlock)failure {
    [self CGET: urlString parameters: parameters progress: nil success: success failure: failure];
}

+ (void)CPOST:(NSString *)urlString
   parameters:(id)parameters
     progress:(void (^)(NSProgress * _Nonnull))uploadProgress
      success:(AFNSuccessBlock)success
      failure:(AFNErrorBlock)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    
    NSURLSessionDataTask *dataTask = [manager POST: urlString parameters: parameters progress: uploadProgress success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        
        success(responseObject,YES);
        [[self dataTaskManager] removeObjectForKey: urlString];
        
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        failure(error);
        [[self dataTaskManager] removeObjectForKey: urlString];
        
    }];
    [[self dataTaskManager] setValue: dataTask forKey: urlString];
    
}
+ (void)CPOST:(NSString *)urlString
   parameters:(id)parameters success: (AFNSuccessBlock)success
      failure:(AFNErrorBlock)failure {
    
    [self CPOST: urlString parameters: parameters progress: nil success: success failure: failure];
}

+ (void)CPUT:(nullable NSString *)urlString
parameters:(nullable id)parameters
   success:(nullable AFNSuccessBlock)success
   failure:(nullable AFNErrorBlock)failure {
     AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *dataTask =  [manager PUT: urlString parameters: parameters success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject,YES);
        [[self dataTaskManager] removeObjectForKey: urlString];
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
        [[self dataTaskManager] removeObjectForKey: urlString];
    }];
    [[self dataTaskManager] setValue: dataTask forKey: urlString];
}

+ (void)CPATCH:(nullable NSString *)urlString
  parameters:(nullable id)parameters
     success:(nullable AFNSuccessBlock)success
     failure:(nullable AFNErrorBlock)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *dataTask =  [manager PATCH: urlString parameters: parameters success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject,YES);
        [[self dataTaskManager] removeObjectForKey: urlString];
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
        [[self dataTaskManager] removeObjectForKey: urlString];
    }];
    [[self dataTaskManager] setValue: dataTask forKey: urlString];
    
}

+ (void)CDELETE:(nullable NSString *)urlString
   parameters:(nullable id)parameters
      success:(nullable AFNSuccessBlock)success
      failure:(nullable AFNErrorBlock)failure {
    
    AFHTTPSessionManager *manager = [self manager];
    NSURLSessionDataTask *dataTask =  [manager DELETE: urlString parameters: parameters success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        success(responseObject,YES);
        [[self dataTaskManager] removeObjectForKey: urlString];
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        failure(error);
        [[self dataTaskManager] removeObjectForKey: urlString];
    }];
    [[self dataTaskManager] setValue: dataTask forKey: urlString];
}

+ (void)downloadWithUrlSring:(NSString *)urlString
                    savePath:(NSString *)savePath
                    progress:(void (^)(NSProgress * _Nonnull))downloadProgress
           completionHandler:(void (^)(NSString * _Nonnull, NSError * _Nonnull))completion {
    
    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration: configuration];
    
    NSURL *URL = [NSURL URLWithString: urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL: URL];
    
    NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest: request progress: ^(NSProgress * _Nonnull progress) {
        
        NetCLog(@"下载任务进度 == %@",downloadProgress);
        downloadProgress(progress);
        
    } destination: ^NSURL *(NSURL *targetPath, NSURLResponse *response) {
        NSURL *documentsDirectoryURL;
        if (savePath == nil||savePath.length < 2) {
            documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory: NSDocumentDirectory inDomain: NSUserDomainMask appropriateForURL: nil create: NO error: nil];
        }
        else
        {
            documentsDirectoryURL = [NSURL fileURLWithPath: savePath];
        }
        
        return [documentsDirectoryURL URLByAppendingPathComponent: [response suggestedFilename]];
    } completionHandler: ^(NSURLResponse *response, NSURL *filePath, NSError *error) {
        completion([filePath relativeString],error);
        NetCLog(@"文件下载到 == %@", filePath);
    }];
    [downloadTask resume];
}

+ (void)cancelRequest:(NSString *)urlString {
   id object = [[self dataTaskManager] objectForKey: urlString];
    if ([object isKindOfClass: [NSURLSessionDataTask class]]) {
        [object cancel];
    }
}

+ (void)cancelAllRequest {
    [[[self manager] operationQueue] cancelAllOperations];
}

+ (BOOL)urlIsRequest:(nullable NSString *)urlString {
    id object =  [[self dataTaskManager] objectForKey: urlString];
    if (object) {
        return YES;
    }
    else
        return NO;
}

+ (void)pauseDownLoadWithURL:(NSString*)urlString {
    
}
//恢复下载
+ (void)reuseDownLoadWithURL:(nullable NSString *)urlString {
    
}

+ (void)uploadImageWithUrlString:(nullable NSString *)urlString
                     parameters:(nullable id)parameters
                          image:(nullable UIImage*)image
                       progress:(nullable void (^)(NSProgress *_Nonnull downloadProgress))uploadProgress
                        success:(nullable AFNSuccessBlock)success
                        failure:(nullable AFNErrorBlock)failure {

    AFHTTPSessionManager *manager = [self manager];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects: @"text/html",@"text/plain",@"application/json", nil];
    
    [manager POST: urlString parameters: parameters constructingBodyWithBlock: ^(id<AFMultipartFormData>  _Nonnull formData) {
      
        NSData *data = UIImageJPEGRepresentation(image, 0.88);
        
        
        // 在网络开发中，上传文件时，是文件不允许被覆盖，文件重名
        // 要解决此问题，
        // 可以在上传时使用当前的系统事件作为文件名
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        // 设置时间格式
        formatter.dateFormat = @"yyyyMMddHHmmss";
        NSString *str = [formatter stringFromDate: [NSDate date]];
        NSString *fileName = [NSString stringWithFormat: @"%@.png", str];
        
        //上传
        /*
         此方法参数
         1. 要上传的[二进制数据]
         2. 对应网站上[upload.php中]处理文件的[字段"file"]
         3. 要保存在服务器上的[文件名]
         4. 上传文件的[mimeType]
         */
        [formData appendPartWithFileData: data name: @"headimg" fileName: fileName mimeType: @"image/png"];
    } progress: ^(NSProgress * _Nonnull uploadProgress) {
         NetCLog(@"上传图片进度 == %f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
    } success: ^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (success) {
            success(responseObject,YES);
        }
        
    } failure: ^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (failure) {
            failure(error);
        }
    }];
    
}

@end
